﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using System.Xml.Linq;
using Mrsoft.Update.Common;
using System.Runtime.InteropServices;

namespace Mrsoft {

    [Guid("F3F54BC2-D6D1-4A85-B943-16287ECEA64C")]
    public class UpdatePlugin : IMrsoft {

        public void Run() {
            GetUpdateInfoFromInternet();
        }

        private readonly Config<int> _softConfig = new Config<int>("./ver.conf", "soft", 41);

        private readonly Config<int> _dataConfig = new Config<int>("./ver.conf", "data", 0);

        /// <summary>
        /// 从网络上获取更新信息
        /// </summary>
        private void GetUpdateInfoFromInternet() {
            //获取服务器信息
            var webString = WebEngine.FormattInternetResultToXmlString(WebEngine.DownloadString("http://dati.qiniudn.com/ver.xml"));//"http://xiaolanchong.duapp.com/xiao/ver.jsp"));
            if (!string.IsNullOrEmpty(webString)) {
                int soft, data; string info;
                //解析服务器信息
                if (GetInfoFromXml(webString, out soft, out data, out info)) {
                    //基础数据获取
                    var dataPath = Path.Combine(Application.StartupPath, "system\\default.7z");
                    if (!File.Exists(dataPath) ||
                        data > _dataConfig.Value) {
                        GetAndSaveGameData(data, dataPath);
                    }
                    if (soft > _softConfig.Value)
                        AskUpdate(soft, info);
                }
            } else {
                ShowError("未能从服务器获取到信息！");
            }
        }

        /// <summary>
        /// 下载并且加密保存游戏数据
        /// </summary>
        /// <param name="ver"></param>
        /// <param name="path"></param>
        private void GetAndSaveGameData(int ver, string path) {
            //下载数据文件
            var buffer = WebEngine.DownloadData(string.Format("http://dati.qiniudn.com/data_{0}.xml", ver));
            using (var ms = new MemoryStream(buffer)) {
                string dir = path.Remove(path.LastIndexOf("\\"));
                if (!Directory.Exists(dir))
                    Directory.CreateDirectory(dir);
                using (var fs = File.Open(path, FileMode.Create)) {
                    var compressor = new SevenZip.SevenZipCompressor();
                    compressor.CompressStream(ms, fs, "sunyu87");
                }
                _dataConfig.Value = ver;
            }
        }

        /// <summary>
        /// 问询用户是否进行更新
        /// </summary>
        /// <param name="soft"></param>
        /// <param name="info"></param>
        private void AskUpdate(int soft, string info) {
            var askMsg = string.Format("本地版本：{0}\r\n最新版本：{1}\r\n更新内容如下：\r\n{2}\r\n是否执行更新？", _softConfig.Value, soft, info);
            var dr = MessageBox.Show(askMsg, "更新提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (dr == DialogResult.Yes) {
                var downlist = new Queue<string>();
                GetSoftDownloadList(soft, downlist);
                if (downlist.Count > 0)
                    Application.Run(new FrmUpdate(_softConfig, downlist));
            }
        }

        /// <summary>
        /// 向服务器查询需要更新的部分
        /// </summary>
        /// <param name="soft"></param>
        /// <param name="downlist"></param>
        private void GetSoftDownloadList(int soft, Queue<string> downlist) {
            _softConfig.Value = _softConfig.Value < 41 ? 41 : _softConfig.Value;
            for (int ver = _softConfig.Value; ver < soft; )
            {
                ver++;
                downlist.Enqueue(string.Format("http://dati.qiniudn.com/update_{0}.zip", ver));
            }
        }

        /// <summary>
        /// 解析更新数据
        /// </summary>
        /// <param name="xml"></param>
        /// <param name="soft"></param>
        /// <param name="data"></param>
        /// <param name="info"></param>
        /// <returns></returns>
        private bool GetInfoFromXml(string xml, out int soft, out int data, out string info) {
            data = soft = 0;
            info = null;
            try {
                var xDoc = XDocument.Parse(xml);
                if (xDoc.Root != null) {
                    var strSoft = xDoc.Root.Attribute("soft").Value;
                    var strData = xDoc.Root.Attribute("data").Value;
                    soft = int.Parse(strSoft);
                    data = int.Parse(strData);
                    info = xDoc.Root.Value.Trim();
                    return true;
                }
            }
            catch (Exception ex) {
                ShowError(ex.Message);
            }
            return false;
        }

        private void ShowError(string errorMsg) {
            MessageBox.Show(errorMsg, "错误提示");
        }
    }
}
